﻿using System;
using System.Runtime.InteropServices;

namespace FFACETools
{
	public partial class FFACE
	{
		#region Constants

		/// <summary>
		/// Message for not implimented exceptions
		/// </summary>
		private const string NEED_v410_14_OR_HIGHER = "FFACETools requires FFACE v4.1.0.14 or higher";

		/// <summary>
		/// Name of the FFACE library
		/// </summary>
		private const string FFACE_LIBRARY = "FFACE.dll";

		#endregion

		#region Members

		/// <summary>
		/// The path to Windower's auto-generated resources.xml
		/// </summary>
		public static string WindowerPath { get; set; }

		/// <summary>
		/// Instance ID generated by FFACE
		/// </summary>
		public int _InstanceID { get; set; }

		/// <summary>
		/// Information about the current player
		/// </summary>
		public PlayerTools Player { get; set; }

		/// <summary>
		/// Information about the player's target
		/// </summary>
		public TargetTools Target { get; set; }

		/// <summary>
		/// Information relating to Party/Alliance
		/// </summary>
		public PartyTools Party { get; set; }

		/// <summary>
		/// Information about party members
		/// </summary>
		public System.Collections.Generic.Dictionary<byte, PartyMemberTools> PartyMember { get; set; }

		/// <summary>
		/// Information about FFACE timers
		/// </summary>
		public TimerTools Timer { get; set; }

		/// <summary>
		/// Information about the chat system
		/// </summary>
		public ChatTools Chat { get; set; }

		/// <summary>
		/// Information about fishing
		/// </summary>
		public FishTools Fish { get; set; }

		/// <summary>
		/// Information about items
		/// </summary>
		public ItemTools Item { get; set; }

		/// <summary>
		/// Informatin about NPC
		/// </summary>
		public NPCTools NPC { get; set; }

		/// <summary>
		/// Information about menus
		/// </summary>
		public MenuTools Menu { get; set; }

		/// <summary>
		/// Information about search results
		/// </summary>
		public SearchTools Search { get; set; }

		/// <summary>
		/// Link to sending information to windower
		/// </summary>
		public WindowerTools Windower { get; set; }

		/// <summary>
		/// Pyrolol's navigation system
		/// </summary>
		public NavigatorTools Navigator { get; set; }

		#endregion

		#region Constructor/Destructor

		/// <summary>
		/// Constructor that instanciates FFACE
		/// </summary>
		/// <param name="processID"></param>
		public FFACE(int processID)
		{
			// create our FFACE instance
			_InstanceID = CreateInstance((UInt32)processID);

			WindowerPath = "Set this to the Plugins Directory";
			//#region Find Windower Plugin Path

			//System.Diagnostics.Process[] Processes = System.Diagnostics.Process.GetProcessesByName("pol");
			//if (Processes.Length > 0)
			//	foreach (System.Diagnostics.ProcessModule mod in Processes[0].Modules)
			//	{
			//		if (mod.ModuleName.ToLower() == "hook.dll")
			//		{
			//			WindowerPath = mod.FileName.Substring(0, mod.FileName.Length - 8) + @"\plugins\";
			//			break;
			//		}
			//	}

			//if (String.IsNullOrEmpty(WindowerPath))
			//	WindowerPath = "Windower path could not be found";

			//#endregion

			// Find out if we should be using structs or not
			System.Diagnostics.FileVersionInfo fileInfo = System.Diagnostics.FileVersionInfo.GetVersionInfo(FFACE_LIBRARY);

			// Need 4, 1, 0, 14 or later.  Adjust these settings as needed.
			UInt64 version = ((UInt64)fileInfo.FileMajorPart << 48) + ((UInt64)fileInfo.FileMinorPart << 32) + ((UInt64)fileInfo.FileBuildPart << 16) + (UInt64)fileInfo.FilePrivatePart;
			if (fileInfo.FileMajorPart != 4)
				throw new Exception(NEED_v410_14_OR_HIGHER);
			else if (version < 0x000400010000000EUL)			// 0004 0001 0000 000E (4, 1, 0, 14)
				throw new Exception(NEED_v410_14_OR_HIGHER);

			/*if (fileInfo.FileMajorPart != 4)
				throw new Exception(NEED_v410_14_OR_HIGHER);
			else if (fileInfo.FileMinorPart < 1)
				throw new Exception(NEED_v410_14_OR_HIGHER);
			else if (fileInfo.FileBuildPart < 0)
				throw new Exception(NEED_v410_14_OR_HIGHER);
			else if (fileInfo.FilePrivatePart < 14)
				throw new Exception(NEED_v410_14_OR_HIGHER);*/


			// instantiate our classes
			Player	    = new PlayerTools(_InstanceID);
			Target	    = new TargetTools(_InstanceID);
			Party	    = new PartyTools(_InstanceID);
			Fish		= new FishTools(_InstanceID);
			Windower	= new WindowerTools(_InstanceID);
			Timer	    = new TimerTools(_InstanceID);
			Chat		= new ChatTools(_InstanceID);
			Item		= new ItemTools(_InstanceID);
			NPC		    = new NPCTools(_InstanceID);
			Menu		= new MenuTools(_InstanceID);
			Search	    = new SearchTools(_InstanceID);
			Navigator   = new NavigatorTools(this);

			#region Party Members

			// instantiate our party members
			PartyMember = new System.Collections.Generic.Dictionary<byte, PartyMemberTools>();
			PartyMember.Add(0, new PartyMemberTools(_InstanceID, 0));
			PartyMember.Add(1, new PartyMemberTools(_InstanceID, 1));
			PartyMember.Add(2, new PartyMemberTools(_InstanceID, 2));
			PartyMember.Add(3, new PartyMemberTools(_InstanceID, 3));
			PartyMember.Add(4, new PartyMemberTools(_InstanceID, 4));
			PartyMember.Add(5, new PartyMemberTools(_InstanceID, 5));
			PartyMember.Add(6, new PartyMemberTools(_InstanceID, 6));
			PartyMember.Add(7, new PartyMemberTools(_InstanceID, 7));
			PartyMember.Add(8, new PartyMemberTools(_InstanceID, 8));
			PartyMember.Add(9, new PartyMemberTools(_InstanceID, 9));
			PartyMember.Add(10, new PartyMemberTools(_InstanceID, 10));
			PartyMember.Add(11, new PartyMemberTools(_InstanceID, 11));
			PartyMember.Add(12, new PartyMemberTools(_InstanceID, 12));
			PartyMember.Add(13, new PartyMemberTools(_InstanceID, 13));
			PartyMember.Add(14, new PartyMemberTools(_InstanceID, 14));
			PartyMember.Add(15, new PartyMemberTools(_InstanceID, 15));
			PartyMember.Add(16, new PartyMemberTools(_InstanceID, 16));
			PartyMember.Add(17, new PartyMemberTools(_InstanceID, 17));

			#endregion

		} // @ public FFACEWrapper(uint processID)

		/// <summary>
		/// Destructor
		/// </summary>
		~FFACE()
		{
		  if (!_InstanceID.Equals(0)) {
		    try {
		      DeleteInstance(_InstanceID);
		    }
		    catch {
		    }
		  }
		} // @ ~FFACEWrapper()

		#endregion

	} // @ public class FFACE
}
